package com.AdvancedDemos.继承;

public class abstract类_模板设计模式 {
    public static void main(String[] args) {
        A3 temp = new B2();
        temp.test();

        //抽象类不能实例化,因为可能含有抽象方法,因为抽象函数没有方法体,调用会出错
//        A3 t = new A3();//'A3' 为 abstract；无法实例化

        //演示模板设计模式
        System.out.println("-----模板设计模式----");
        Zi1 zi1 = new Zi1();
        zi1.play();
        System.out.println("-------------------");
        Zi2 zi2 = new Zi2();
        zi2.play();
        System.out.println("-------------------");
    }
}

abstract class A3 {//抽象类中可以含有抽象函数,但不是必须的,其他与普通类无异

    abstract public void test();//当父类中某个函数仅仅需要被继承,具体实现交由子类实现时,可以用abstract关键字,在抽象类中声明抽象函数
    //abstract 不能和 final 同时使用,互相矛盾
}

class B2 extends A3 {
    //子类中必须重新实现test(),否则也应当声明为abstract,由子子类来实现test()...
    @Override
    public void test() {
        System.out.println("This is class B2");
    }
}


class Zi1 extends Fu {
    @Override
    void what() {
        System.out.println("玩个勾八玩,学习!");
    }
}

class Zi2 extends Fu {
    @Override
    void what() {
        System.out.println("玩一下下好了~");
    }
}

abstract class Fu {

    final void play() {//模板方法设计模式:将类声明成抽象的,再声明一个模版方法一个抽象方法,模版方法中一部分已经确定的给出具体实现,剩余未定部分抽出写成抽象方法,等待不同子类给出具体实现 ; 一般模版方法用final修饰,使得子类中无法重写该方法,从而避免子类中因为重写了该方法而覆盖了模版方法,使得模版函数不可见,破坏了模板
        System.out.println("开机");
        what();//what并没有具体实现,具体玩什么有子类实现决定
        System.out.println("关机");
    }

    abstract void what();
}
